/*
 * Copyright 2009 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel.utils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * json格式的输出结果
 */
public class JSonResult extends SimpleResult {

    protected Map<String, Object> map = new HashMap<String, Object>();

    protected String charset = "utf-8";
    protected String contentType = "application/javascript";

    /**
     * 构造方法
     * @param charset 输出使用的文本编码
     * @param contentType 输出的内容类型
     */
    public JSonResult(String charset, String contentType) {
        this.charset = charset;
        this.contentType = contentType;
    }

    /**
     * 构造方法，使用默认的"application/javascript"内容类型
     * @param charset 输出使用的文本编码
     */
    public JSonResult(String charset) {
        this.charset = charset;
    }

    /**
     * 默认构造方法，使用默认的"application/javascript"内容类型及utf-8文本编码
     */
    public JSonResult() {
    }

    /**
     * 去掉一个属性
     * @param name 属性名称
     * @return 自己
     */
    public JSonResult remove(String name) {
        map.remove(name);
        return this;
    }

    /**
     * 设置一个属性<br>
     * 对null类型，{@link String}类型，{@link java.util.Collection}类型以及数组类型特殊处理。
     * @param name 属性名称
     * @param value 属性值
     * @return 自己
     */
    public JSonResult set(String name, Object value) {
        map.put(name, value);
        return this;
    }

    /**
     * 向客户端输出json格式的字符串
     * @throws IOException 输出异常
     */
    public void render() throws IOException {
        HttpServletResponse response = context.getResponse();
        response.setContentType(contentType);
        response.setCharacterEncoding(charset);
        response.getWriter().print(this);
    }

    /**
     * 以json格式输出字符串
     * @return json格式字符串
     */
    public String toString() {
        if (map.isEmpty()) {
            return "{}";
        }
        StringBuilder sb = new StringBuilder("{");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            sb.append('\"').append(entry.getKey()).append("\":").append(toString(entry.getValue())).append(',');
        }
        sb.setCharAt(sb.length() - 1, '}');
        return sb.toString();
    }

    /**
     * 以javascript的值方式输出字符串。<br>
     * 对null类型，{@link String}类型，{@link java.util.Collection}类型以及数组类型特殊处理，其余类型直接执行{@link Object#toString()}方法。
     * @param obj 属性值
     * @return 字符串
     */
    public static String toString(final Object obj) {
        if(obj==null) return "null";
        if (obj instanceof String) {
            return '"' + obj.toString().replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r") + '"';
        } else if (obj instanceof Collection) {
            Collection list = (Collection) obj;
            if(list.isEmpty()) return "[]";
            StringBuilder sb = new StringBuilder("[");
            for (Object o : list) {
                sb.append(toString(o)).append(',');
            }
            sb.setCharAt(sb.length() - 1, ']');
            return sb.toString();
        } else if(obj.getClass().isArray()) {
            int len = Array.getLength(obj);
            if(len==0) return "[]";
            StringBuilder sb = new StringBuilder("[");
            for (int i = 0; i < len; i++) {
                sb.append(toString(Array.get(obj, i))).append(',');
            }
            sb.setCharAt(sb.length() - 1, ']');
            return sb.toString();
        } else {
            return obj.toString();
        }
    }

    /**
     * 获得文本编码
     * @return 编码
     */
    public String getCharset() {
        return charset;
    }

    /**
     * 获得内容类型
     * @return 类型
     */
    public String getContentType() {
        return contentType;
    }
}
